package com.ev.apis.controller.mes;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ev.asl.dao.MoldingProductionInstructionDao;
import com.ev.asl.vo.voBillOfPull.KisReceiveStockVo;
import com.ev.custom.domain.DictionaryDO;
import com.ev.custom.service.DictionaryService;
import com.ev.framework.config.Constant;
import com.ev.framework.config.ConstantForGYL;
import com.ev.framework.utils.*;
import com.ev.mes.dao.ProductionFeedingDetailDao;
import com.ev.mes.domain.*;
import com.ev.mes.service.*;
import com.ev.scm.domain.StockDO;
import com.ev.scm.service.PurchaseItemService;
import com.ev.scm.service.StockOutItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.ev.framework.annotation.EvApiByToken;
import com.ev.apis.model.DsResultResponse;
import com.ev.custom.service.MaterielService;
import com.google.common.collect.Maps;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

/**
 * 生产投料管理
 *
 * @author gumingjie
 * @email gumingjie.qi@gmail.com
 * @date 2019-11-22 09:51:41
 */

@Api(value = "/", tags = "生产投料API")
@RestController
public class ProductionFeedingApiController {
	@Autowired
	private ProductionFeedingDetailDao productionFeedingDetailDao;
	@Autowired
	private ProductionFeedingService productionFeedingService;
	@Autowired
	private BomService bomService;
	@Autowired
	private MoldingProductionInstructionDao moldingProductionInstructionDao;
	@Autowired
	private ProductionPlanService productionPlanService;
	@Autowired
	private ProductionFeedingDetailService productionFeedingDetailService;
	@Autowired
	private DictionaryService dictionaryService;
	@Autowired
	private StockOutItemService stockOutItemService;
	@Autowired
	private PurchaseItemService purchaseItemService;
	@Autowired
	private ProductionFeedingAlterationService alterationService;
	@Autowired
	private MaterielService materielService;

	/**
	 * 获取生产投料父项列表(上表)
	 * 说明：
	 * 本表数据由生产计划单关联对应的生产投料单、生产领料单、生产报废单、即时库存等数据生成。上表数据选中下表动态显示相应的数据
	 *
	 * @date 2019-11-28
	 * @author gumingjie
	 *
	 */
	@EvApiByToken(value = "/apis/productionFeeding/list", method = RequestMethod.POST, apiTitle = "生产投料列表")
	@ApiOperation("获取生产投料父项产品列表")
	public R list(
			@ApiParam(value = "当前第几页", required = true) @RequestParam(value = "pageno", defaultValue = "1") int pageno,
			@ApiParam(value = "一页多少条", required = true) @RequestParam(value = "pagesize", defaultValue = "20") int pagesize,
			@ApiParam(value = "生产计划单号") @RequestParam(value = "productionPlanNo", defaultValue = "", required = false) String productionPlanNo,
			@ApiParam(value = "部门ID") @RequestParam(value = "deptId", defaultValue = "", required = false) Long deptId,
			@ApiParam(value = "开始时间") @RequestParam(value = "startTime", defaultValue = "", required = false) String startTime,
			@ApiParam(value = "结束时间") @RequestParam(value = "endTime", defaultValue = "", required = false) String endTime,
//			@ApiParam(value = "生产投料名称", required = false) @RequestParam(value = "productionFeedingName", defaultValue = "", required = false) String productionFeedingName,
			@ApiParam(value = "产品代码") @RequestParam(value = "serialNo", defaultValue = "", required = false) String serialNo,
			@ApiParam(value = "状态ID") @RequestParam(value = "status", defaultValue = "", required = false) Integer status,
            @ApiParam(value = "需排序字段") @RequestParam(value = "sort",defaultValue = "",required = false)  String sort,
            @ApiParam(value = "升（asc）降(desc)序") @RequestParam(value = "order",defaultValue = "",required = false)  String order) {
		// 查询列表数据
		Map<String, Object> params = Maps.newHashMapWithExpectedSize(10);
        // 自定义排序规则
        if (StringUtils.isNoneEmpty(sort)) {
            params.put("offset", 0);
            params.put("limit", 1);
            params.put("isPlan",1);
            List<Map<String, Object>> maps = this.productionFeedingService.listForMap(params);
            if (maps.size() > 0 && maps.get(0).containsKey(sort)) {
                params.put("sort", sort);
                params.put("order", StringUtils.isOrder(order));
            }
        }
		params.put("productionPlanNo", productionPlanNo);
		params.put("deptId", deptId);
		params.put("startTime", startTime);
		params.put("endTime", endTime);

		params.put("serialNo", serialNo);
		params.put("status", status);

		params.put("offset", (pageno - 1) * pagesize);
		params.put("limit", pagesize);
		params.put("delFlag", 0);
		params.put("isPlan",1);
		Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);
		List<Map<String, Object>> data = productionFeedingService.listForMap(params);
		Map<String, Object> totalMap = productionFeedingService.countForMap(params);
		int total = Integer.parseInt(totalMap.get("total").toString());
		if (data != null && data.size() > 0) {
			DsResultResponse dsRet = new DsResultResponse();
			dsRet.setDatas(data);
			dsRet.setPageno(pageno);
			dsRet.setPagesize(pagesize);
			dsRet.setTotalRows(total);
			dsRet.setTotalPages((total + pagesize - 1) / pagesize);
			results.put("data", dsRet);
			results.put("total", totalMap);
		}
		return R.ok(results);
	}
	@EvApiByToken(value = "/apis/productionFeeding/listSyncLog", method = RequestMethod.GET, apiTitle = "生产投料列表")
	@ApiOperation("获取同步日志")
	public R listSyncLog(
			@ApiParam(value = "当前第几页", required = true) @RequestParam(value = "pageno", defaultValue = "1") int pageno,
			@ApiParam(value = "一页多少条", required = true) @RequestParam(value = "pagesize", defaultValue = "20") int pagesize,
			@ApiParam(value = "日志类型", required = true)Integer type,
			@ApiParam(value = "状态：0-未处理；1-已处理", required = true)Integer status) {
		// 查询列表数据
		Map<String, Object> params = Maps.newHashMapWithExpectedSize(10);
		params.put("offset", (pageno - 1) * pagesize);
		params.put("limit", pagesize);
		params.put("type",type);
		params.put("status",status);
		Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);
		List<Map<String, Object>> data = productionFeedingDetailDao.listSyncLog(params);
		int count = productionFeedingDetailDao.countSyncLog(params);
		if (data != null && data.size() > 0) {
			DsResultResponse dsRet = new DsResultResponse();
			dsRet.setDatas(data);
			dsRet.setPageno(pageno);
			dsRet.setPagesize(pagesize);
			dsRet.setTotalRows(count);
			dsRet.setTotalPages((count + pagesize - 1) / pagesize);
			results.put("result",dsRet);
		}
		return R.ok(results);
	}
	@Transactional(rollbackFor = Exception.class)
	@EvApiByToken(value = "/apis/productionFeeding/auditSyncLog", method = RequestMethod.GET, apiTitle = "完成同步日志")
	@ApiOperation("完成同步日志")
	public R auditSyncLog(
			@ApiParam(value = "日志主键", required = true)Long id) {
		SyncLogDO syncLogDO = new SyncLogDO();
		syncLogDO.setId(id);
		syncLogDO.setStatus(1);
		productionFeedingDetailDao.updateSyncLog(syncLogDO);
		return R.ok("操作成功");
	}

	/**
	 * 获取生产投料子项列表(下表)
	 * 说明：
	 * 本表数据由生产计划单关联对应的生产投料单、生产领料单、生产报废单、即时库存等数据生成。上表数据选中下表动态显示相应的数据
	 *
	 * @date 2019-11-28
	 * @author gumingjie
	 *
	 */
	@EvApiByToken(value = "/apis/productionFeeding/childList", method = RequestMethod.POST, apiTitle = "生产投料列表")
	@ApiOperation("获取生产投料子项目列表")
	public R childList(
			@ApiParam(value = "当前第几页", required = true) @RequestParam(value = "pageno", defaultValue = "1") int pageno,
			@ApiParam(value = "一页多少条", required = true) @RequestParam(value = "pagesize", defaultValue = "20") int pagesize,
            @ApiParam(value = "生产投料单号") @RequestParam(value = "planNo", defaultValue = "", required = false) String planNo,
			@ApiParam(value = "状态ID") @RequestParam(value = "auditSign", defaultValue = "", required = false) Integer auditSign,
            @ApiParam(value = "物料名称") @RequestParam(value = "materialsName", defaultValue = "", required = false) String materialsName,
            @ApiParam(value = "开始时间") @RequestParam(value = "startTime", defaultValue = "", required = false) String startTime,
            @ApiParam(value = "结束时间") @RequestParam(value = "endTime", defaultValue = "", required = false) String endTime,
			@ApiParam(value = "父项产品ID") @RequestParam(value = "headId", defaultValue = "", required = false) Long headId) {
		// 查询列表数据
		Map<String, Object> params = Maps.newHashMap();

        params.put("planNo", planNo);
        params.put("materialsName", materialsName);
        params.put("startTime", startTime);
        params.put("endTime", endTime);
		params.put("headId", headId);
		params.put("auditSign", auditSign);

		params.put("isPlan",1);
		params.put("offset", (pageno - 1) * pagesize);
		params.put("limit", pagesize);
		Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);
		List<Map<String, Object>> data = productionFeedingDetailService.listForMap(params);

		Map<String, Object> param = Maps.newHashMap();
		param.put("isPc",1);
		// 获取实时库存
		List<Map<String, Object>> stockListForMap = materielService.stockListForMap(param);
		int total = productionFeedingDetailService.countForMap(params);
		if (data.size() > 0) {
			// quoteCount  可领数量
			for (Map<String, Object> map : data) {
				if (stockListForMap.size() > 0) {
					double availableCount = 0.0d;
					for (Map<String, Object> stockList : stockListForMap) {
						if (Objects.equals(stockList.get("materielId").toString(), map.get("materielId").toString())) {
							// 如果没有批次要求则查出所有该商品的可用数量累计
							if (!map.containsKey("batchNo")) {
								availableCount += Double.parseDouble(stockList.get("availableCount").toString());
								continue;
							}
							// 若制定了批次则将这一批次的可用数量查出记为实时数量
							if (Objects.equals(stockList.get("batch").toString(), map.get("batchNo").toString())) {
								availableCount += Double.parseDouble(stockList.get("availableCount").toString());
							}

						}
					}
					map.put("availableCount", availableCount);
				}
			}
			results.put("data", new DsResultResponse(pageno,pagesize,total,data));
		}
		return R.ok(results);
	}

	/**
	 * 获取生产投料子项dialog列表
	 * 说明：
	 * 本表数据由生产计划单关联对应的生产投料单、生产领料单、生产报废单、即时库存、源单剩余数量等数据生成。
	 *
	 * @date 2020-03-09
	 * @author gumingjie
	 *
	 */
	@EvApiByToken(value = "/apis/productionFeeding/dialog", method = RequestMethod.POST, apiTitle = "生产投料子项目列表")
	@ApiOperation("获取生产投料子项目列表")
	public R childListDialog(
			@ApiParam(value = "当前第几页", required = true) @RequestParam(value = "pageno", defaultValue = "1") int pageno,
			@ApiParam(value = "一页多少条", required = true) @RequestParam(value = "pagesize", defaultValue = "5") int pagesize,
			@ApiParam(value = "生产投料单号") @RequestParam(value = "planNo", defaultValue = "", required = false) String planNo,
			@ApiParam(value = "物料名称") @RequestParam(value = "materialsName", defaultValue = "", required = false) String materialsName,
			@ApiParam(value = "开始时间") @RequestParam(value = "startTime", defaultValue = "", required = false) String startTime,
			@ApiParam(value = "结束时间") @RequestParam(value = "endTime", defaultValue = "", required = false) String endTime,
			@ApiParam(value = "dialog类型：生产领用0，采购申请1",required = true) @RequestParam(value = "dialogType",defaultValue = "")  Integer dialogType,
			@ApiParam(value = "父项产品ID") @RequestParam(value = "headId", defaultValue = "", required = false) Long headId) {
		// 查询列表数据
		Map<String, Object> params = Maps.newHashMap();

		params.put("planNo", planNo);
		params.put("materialsName", materialsName);
		params.put("startTime", startTime);
		params.put("endTime", endTime);
		params.put("headId", headId);

		params.put("auditSign", Constant.OK_AUDITED);
		params.put("isPlan",1);

		Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);
		List<Map<String, Object>> data = productionFeedingDetailService.listForMap(params);
		DictionaryDO dictionaryDO = dictionaryService.get(ConstantForGYL.SCTLD);
		String thisSourceTypeName = dictionaryDO.getName();

		Map<String, Object> param = Maps.newHashMap();
		param.put("isPc",1);
		// 获取实时库存
		// 优化（将需要查询的物料提取出来）
		List<Map<String, Object>> stockListForMap = materielService.stockListForMap(param);
		if (data.size() > 0) {
			Map<String,Object> sourceParam;
			BigDecimal bySource =null;
			// quoteCount  可领数量
			for (Map<String, Object> map : data) {
				// 限额领料
				if(Integer.parseInt(map.get("isQuota").toString())!=0){
					sourceParam = Maps.newHashMap();
					sourceParam.put("sourceId",map.get("id"));
					sourceParam.put("sourceType", ConstantForGYL.SCTLD);
					switch (dialogType){
						case 0:
							bySource = stockOutItemService.getCountBySource(sourceParam);
							break;
						case 1:
							bySource = purchaseItemService.getInCountOfPurchase(sourceParam);
							break;
						default:
							break;
					}
					BigDecimal countByOutSource = bySource==null?BigDecimal.ZERO:bySource;
					BigDecimal planFeedingCount = MathUtils.getBigDecimal(map.get("planFeedingCount")).subtract(countByOutSource);
					if (planFeedingCount.compareTo(BigDecimal.ZERO) <= 0) {
						map.put("quoteCount", 0);
					}else {
						map.put("quoteCount", planFeedingCount);
					}
				}
			}
			List<Map<String, Object>> quoteLists = data
					.stream()
					.filter(stringObjectMap -> !stringObjectMap.containsKey("quoteCount")||MathUtils.getBigDecimal(stringObjectMap.get("quoteCount")).compareTo(BigDecimal.ZERO)>0)
					.collect(Collectors.toList());
			if (quoteLists.size() > 0) {
				List<Map<String, Object>> quoteList = PageUtils.startPage(quoteLists, pageno, pagesize);
				for (Map<String, Object> map : quoteList) {
					map.put("thisSourceType", ConstantForGYL.SCTLD);
					map.put("thisSourceTypeName", thisSourceTypeName);
					if (stockListForMap.size() > 0) {
						double availableCount = 0.0d;
						for (Map<String, Object> stockList : stockListForMap) {
							if (Objects.equals(stockList.get("materielId").toString(), map.get("materielId").toString())) {
								// 如果没有批次要求则查出所有该商品的可用数量累计
								if (!map.containsKey("batchNo")) {
									availableCount += Double.parseDouble(stockList.get("availableCount").toString());
									continue;
								}
								// 若制定了批次则将这一批次的可用数量查出记为实时数量
								if (Objects.equals(stockList.get("batch").toString(), map.get("batchNo").toString())) {
									availableCount += Double.parseDouble(stockList.get("availableCount").toString());
								}

							}
						}
						map.put("availableCount", availableCount);
					}
				}
				results.put("data", new DsResultResponse(pageno,pagesize,quoteLists.size(),quoteList));
			}
		}
		return R.ok(results);
	}


	/**
	 * 生产投料列表(生产计划待领列表）
	 * 手机端
	 *
	 * @date 2020-02-26
	 * @author gumingjie
	 */
	@EvApiByToken(value = "/apis/productionFeeding/phoneList", method = RequestMethod.POST, apiTitle = "生产投料列表(生产计划待领列表)")
	@ApiOperation("获取生产投料列表(生产计划待领列表)")
	public R phoneList(
			@ApiParam(value = "当前第几页", required = true) @RequestParam(value = "pageno", defaultValue = "1") int pageno,
			@ApiParam(value = "一页多少条", required = true) @RequestParam(value = "pagesize", defaultValue = "20") int pagesize,
			@ApiParam(value = "生产投料单号") @RequestParam(value = "planNo", defaultValue = "", required = false) String planNo,
			@ApiParam(value = "物料名称") @RequestParam(value = "materialsName", defaultValue = "", required = false) String materialsName,
			@ApiParam(value = "开始时间") @RequestParam(value = "startTime", defaultValue = "", required = false) String startTime,
			@ApiParam(value = "审核状态") @RequestParam(value = "auditSign", defaultValue = "", required = false) Long auditSign,
			@ApiParam(value = "是否为手机端") @RequestParam(value = "isPhone", defaultValue = "", required = false) Integer isPhone,
			@ApiParam(value = "结束时间") @RequestParam(value = "endTime", defaultValue = "", required = false) String endTime,
			@ApiParam(value = "父项产品ID") @RequestParam(value = "headId", defaultValue = "", required = false) Long headId) {
		// 查询列表数据
		Map<String, Object> params = Maps.newHashMap();

		params.put("planNo", planNo);
		params.put("materialsName", materialsName);
		params.put("startTime", startTime);
		params.put("endTime", endTime);
		params.put("headId", headId);
		params.put("auditSign", auditSign);
		params.put("isPhone", isPhone);

		params.put("isPlan",1);
		params.put("offset", (pageno - 1) * pagesize);
		params.put("limit", pagesize);
		Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);
		List<Map<String, Object>> data = productionFeedingDetailService.phoneListForMap(params);
		int total = productionFeedingDetailService.phoneCountForMap(params);
		if (data.size() > 0) {
			results.put("data", new DsResultResponse(pageno, pagesize, total, data));
		}
		return R.ok(results);
	}

	/**
	 * 审核生产投料
	 * 限制条件1.已审核不能重复审核2.不是单据审核人不能审核
	 * 将单据状态修改为审核状态，锁定单据不能修改
	 *
	 * @date 2019-11-28
	 * @author gumingjie
	 */
	@Transactional(rollbackFor = Exception.class)
	@EvApiByToken(value = "/apis/productionFeeding/audit", method = RequestMethod.POST, apiTitle = "审核生产投料单")
	@ApiOperation("审核生产投料单")
	public R audit(
			@ApiParam(value = "生产投料单主键", required = true) @RequestParam(value = "id", defaultValue = "") Long id) {
		return productionFeedingService.audit(id);
	}

	/**
	 * 反审核生产投料
	 * 审核生产投料
	 * 限制条件
	 * 1.待审核不能反审核
	 * 2.不是单据审核人不能反审核
	 * 3.有关联单据在不能反审核（即详细列表里领料数量存在或报废数量存在）
	 * 将单据状态修改为审核状态，锁定单据不能修改
	 *
	 * @date 2019-11-29
	 * @author gumingjie
	 */
	@Transactional(rollbackFor = Exception.class)
	@EvApiByToken(value = "/apis/productionFeeding/reverseAudit", method = RequestMethod.POST, apiTitle = "反审核生产投料")
	@ApiOperation("反审核生产投料")
	public R reverseAudit(
			@ApiParam(value = "生产投料主键", required = true) @RequestParam(value = "id", defaultValue = "") Long id) {
		return productionFeedingService.reverseAudit(id);
	}

	/**
	 * 保存生产投料信息（单独生成的生产投料计划）
	 * 1.目前不能反选生产计划单
	 *
	 * @param feedingDO 主表数据
	 * @param childArray 子表数据
	 *
	 * @date 2019-11-29
	 * @author gumingjie
	 */
	@Transactional(rollbackFor = Exception.class)
	@EvApiByToken(value = "/apis/productionFeeding/save", method = RequestMethod.POST, apiTitle = "保存生产投料信息")
	@ApiOperation("保存生产投料信息（单独生成的生产投料计划）")
	public R save(ProductionFeedingDO feedingDO, @ApiParam(value = "子项物料例："+
			"[\r\n" +
			"    {\r\n" +
			"        \"materielId\":15,\r\n" +
			"        \"batchNo\":\"批号001\",\r\n" +
			"        \"planFeeding\":1000\r\n" +
			"    },\r\n" +
			"    {\r\n" +
			"        \"materielId\":16,\r\n" +
			"        \"batchNo\":\"批号002\",\r\n" +
			"        \"planFeeding\":9000\r\n" +
			"    }\r\n" +
			"]"
			, required = true) @RequestParam(value = "childArray", defaultValue = "") String childArray) {
		return productionFeedingService.add(feedingDO, childArray);
	}

	/**
	 * 查看生产投料单详情
	 *
	 * @date 2019-11-29
	 * @author gumingjie
	 */
	@EvApiByToken(value = "/apis/productionFeeding/detail", method = RequestMethod.POST, apiTitle = "查看生产投料信息")
	@ApiOperation("查看生产投料信息")
	public R detail(
			@ApiParam(value = "生产投料Id", required = true) @RequestParam(value = "id", defaultValue = "") Long id) {
		return R.ok(productionFeedingService.getDetailInfo(id));
	}

	/**
	 * 修改生产投料
	 * 限制条件:
	 * 1.已审核单据不能进行反审核
	 * @param feedingDO 需要修改的生产投料信息
	 * @param childArray 生产投料单需要领的物料
	 *
	 * @date 2019-11-29
	 * @author gumingjie
	 */
	@Transactional(rollbackFor = Exception.class)
	@EvApiByToken(value = "/apis/productionFeeding/update", method = RequestMethod.POST, apiTitle = "修改生产投料")
	@ApiOperation("修改生产投料")
	public R update(ProductionFeedingDO feedingDO, @ApiParam(value = "生产投料单需要领的物料数组例："+
			 "[\r\n" +
			 "    {\r\n" +
			 "        \"id\":1,\r\n" +
			 "        \"materielId\":1,\r\n" +
			 "        \"batchNo\":\"批号001\",\r\n" +
			 "        \"planFeeding\":1000\r\n" +
			 "    },\r\n" +
			 "    {\r\n" +
			 "        \"id\":2,\r\n" +
			 "        \"materielId\":2,\r\n" +
			 "        \"batchNo\":\"批号002\",\r\n" +
			 "        \"planFeeding\":9000\r\n" +
			 "    },\r\n" +
			 "    {\r\n" +
			 "        \"materielId\":1,\r\n" +
			 "        \"batchNo\":\"批号004\",\r\n" +
			 "        \"planFeeding\":9000\r\n" +
			 "    }\r\n" +
			 "]"
    ) @RequestParam(value = "childArray", defaultValue = "", required = false) String childArray,
			@ApiParam(value = "被删除的子项目ID") @RequestParam(value = "ids", defaultValue = "", required = false) Long[] ids) {
		return productionFeedingService.edit(feedingDO, childArray, ids);
	}

	/**
	 * 变更生产投料
	 *
	 * @date 2020-04-26
	 * @author gumingjie
	 */
	@Transactional(rollbackFor = Exception.class)
	@EvApiByToken(value = "/apis/productionFeeding/change", method = RequestMethod.POST, apiTitle = "变更生产投料")
	@ApiOperation("变更生产投料")
	public R change(ProductionFeedingDO feedingDO, @ApiParam(value = "生产投料单需要领的物料数组例："+
			"[\r\n" +
			"    {\r\n" +
			"        \"id\":1,\r\n" +
			"        \"materielId\":1,\r\n" +
			"        \"batchNo\":\"批号001\",\r\n" +
			"        \"planFeeding\":1000,\r\n" +
			"        \"facilityId\":1,\r\n" +
			"        \"locationId\":1,\r\n" +
			"        \"processId\":1,\r\n" +
			"        \"stationId\":1,\r\n" +
			"        \"isCollect\":1\r\n" +
			"    },\r\n" +
			"    {\r\n" +
			"        \"id\":2,\r\n" +
			"        \"materielId\":2,\r\n" +
			"        \"batchNo\":\"批号002\",\r\n" +
			"        \"planFeeding\":9000,\r\n" +
			"        \"facilityId\":1,\r\n" +
			"        \"locationId\":1,\r\n" +
			"        \"processId\":1,\r\n" +
			"        \"stationId\":1,\r\n" +
			"        \"isCollect\":1\r\n" +
			"    },\r\n" +
			"    {\r\n" +
			"        \"materielId\":1,\r\n" +
			"        \"batchNo\":\"批号004\",\r\n" +
			"        \"planFeeding\":9000,\r\n" +
			"        \"facilityId\":1,\r\n" +
			"        \"locationId\":1,\r\n" +
			"        \"processId\":1,\r\n" +
			"        \"stationId\":1,\r\n" +
			"        \"isCollect\":1\r\n" +
			"    }\r\n" +
			"]"
	) @RequestParam(value = "childArray", defaultValue = "", required = false) String childArray,
					@ApiParam(value = "被删除的子项目ID") @RequestParam(value = "ids", defaultValue = "", required = false) Long[] ids) {
		return productionFeedingService.change(feedingDO, childArray, ids);
	}

	/**
	 * 查看生产投料单变更详情
	 *
	 * @date 2020-04-26
	 * @author gumingjie
	 */
	@EvApiByToken(value = "/apis/productionFeeding/changeDetail", method = RequestMethod.POST, apiTitle = "查看生产投料单变更详情")
	@ApiOperation("查看生产投料单变更详情")
	public R changeDetail(
			@ApiParam(value = "变更记录", required = true) @RequestParam(value = "id", defaultValue = "") Long id) {
		return R.ok(productionFeedingService.changeDetail(id));
	}

	/**
	 * 查看投料单变更记录列表
	 *
	 * @date 2020-04-26
	 * @author gumingjie
	 */
	@EvApiByToken(value = "/apis/productionFeeding/changeList", method = RequestMethod.POST, apiTitle = "查看投料单变更记录列表")
	@ApiOperation("查看投料单变更记录列表")
	public R changeList(
			@ApiParam(value = "当前第几页", required = true) @RequestParam(value = "pageno", defaultValue = "1") int pageno,
			@ApiParam(value = "一页多少条", required = true) @RequestParam(value = "pagesize", defaultValue = "20") int pagesize,
			@ApiParam(value = "变更人") @RequestParam(value = "createName", defaultValue = "", required = false) String createName,
			@ApiParam(value = "变更人ID") @RequestParam(value = "createId", defaultValue = "", required = false) Long createId,
			@ApiParam(value = "投料单ID") @RequestParam(value = "feedingId", defaultValue = "", required = false) Long feedingId,
			@ApiParam(value = "投料单类型") @RequestParam(value = "type", defaultValue = "", required = false) Integer type,
			@ApiParam(value = "开始时间") @RequestParam(value = "startTime", defaultValue = "", required = false) String startTime,
			@ApiParam(value = "结束时间") @RequestParam(value = "endTime", defaultValue = "", required = false) String endTime
	) {

		// 查询列表数据
		Map<String, Object> params = Maps.newHashMapWithExpectedSize(10);
		params.put("startTime", startTime);
		params.put("endTime", endTime);
		params.put("type", type);
		params.put("createId", createId);
		params.put("feedingId", feedingId);
		params.put("createName", StringUtils.sqlLike(createName));

		params.put("offset", (pageno - 1) * pagesize);
		params.put("limit", pagesize);
		Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);
		List<Map<String, Object>> data = alterationService.listForMap(params);
		int total = alterationService.countForMap(params);
		if (data.size() > 0) {
			results.put("data", new DsResultResponse(pageno,pagesize,total,data));
		}
		return R.ok(results);
	}
	/**
	 *
	 * 爱塞璐根据选择的生产任务单的主键id获取投料数据
	 *
	 * @date 2019-11-30
	 * @author gumingjie
	 */
	@EvApiByToken(value = "/apis/productionPlan/aslGetFeedingByPlanId", method = RequestMethod.POST, apiTitle = "爱塞璐根据选择的生产任务单的主键id获取投料数据")
	@ApiOperation("爱塞璐根据选择的生产任务单的主键id获取投料数据")
	public R aslGetFeedingByPlanId(@ApiParam(value = "生产任务单id", required = true) @RequestParam(value = "id", defaultValue = "") Long id){
		Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);
		List<Map<String, Object>> maps = productionFeedingService.aslGetFeedingByPlanId(id);
		if (ObjectUtil.isEmpty(maps)){
			return R.ok(results);
		}
		Map<Object, Map<String, Object>> collect = maps.stream()
				.collect(Collectors.toMap(map -> map.get("materielId"), map -> map,
						(bom1, bom2) -> {
							bom1.put("planFeeding", new BigDecimal(bom1.get("planFeeding").toString()).add(new BigDecimal(bom2.get("planFeeding").toString())));
							return bom1;
						})
				);
//		Map<String, BigDecimal> collect = maps.stream()
//				.collect(Collectors.groupingBy(map ->map.get("materielId").toString(), CustomCollectors.summingBigDecimal(i -> new BigDecimal(i.get("planFeeding").toString()))));
		results.put("data",collect.values());
		return R.ok(results);
	}
	/**
	 *
	 * 爱塞璐根据选择的生产任务单的主键id获取投料数据
	 *
	 * @date 2019-11-30
	 * @author gumingjie
	 */
	@EvApiByToken(value = "/apis/productionPlan/aslGetFeedingByPlanId2", method = RequestMethod.POST, apiTitle = "爱塞璐根据选择的生产任务单的主键id获取投料数据")
	@ApiOperation("爱塞璐根据选择的生产任务单的主键id获取投料数据")
	public R aslGetFeedingByPlanId2(@ApiParam(value = "生产任务单id", required = true) @RequestParam(value = "id", defaultValue = "") Long id,
									@ApiParam(value = "生产投料单id", required = true) @RequestParam(value = "feedId", defaultValue = "") Long feedId,
									@ApiParam(value = "生产投料单id", required = true) @RequestParam(value = "instructionId", required = false, defaultValue = "") Long instructionId,
									@ApiParam(value = "生产数量", required = true) @RequestParam(value = "num", defaultValue = "",required = false) BigDecimal num){
//		Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);
//		List<Map<String, Object>> list = productionFeedingService.aslGetFeedingByPlanId(id);
//		List<Map<String, Object>> result = new ArrayList<>();
//		//成型日报的原料投入量限制最大数量为4
//		if (!ObjectUtils.isEmpty(list) && list.size()>4){
//			result = list.subList(0,4);
//		}else {
//			result = list;
//		}
//		results.put("data",result);
//		return R.ok(results);
		return getRawMaterialRatio2(id, feedId, num, instructionId);
	}

	public static void main(String[] args) {
		String a = "M/B";
		String b = "M/B";
		HashMap<String, BigDecimal> countMap = new HashMap<>();
		countMap.put(a,new BigDecimal(12));
		countMap.put(b,new BigDecimal(12));
		System.out.println(countMap);
//		HashMap<String, BigDecimal> countMap = new HashMap<>();
//		List<Map<Object, Object>> data = new ArrayList<>();
//		List<BomDO2> distinctBoms = new ArrayList<>();
//		data = distinctBoms.stream()
//					.map(bom -> {
//						HashMap<Object, Object> map = new HashMap<>();
//						map.put("materielId", bom.getChildMaterielId());
//						map.put("materielName", bom.getChildMaterielName());
//							if (countMap.containsKey(bom.getChildMaterielName())){
//								System.out.println("24");
//							}else{
//								System.out.println("2222222222224");
//							}
////						map.put("planFeeding", collectStandardCount.get(bom.getChildMaterielId()).multiply(productionPlanDO.getPlanCount()).setScale(2, BigDecimal.ROUND_HALF_UP));
//						return map;
//					}).collect(Collectors.toList());
//		List<BomDO2> collect = childs.stream().collect(
//				Collectors.collectingAndThen(
//						Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BomDO2::getChildMaterielName))), ArrayList::new));
	}
	public static  <K> Predicate<K> distinctPredicate(Function<K,Object> function){
		ConcurrentHashMap<Object, Boolean> map = new ConcurrentHashMap<>();
		return (t)-> null == map.putIfAbsent(function.apply(t),true);

	}

	/**
	 * 获得产品的子bom信息
	 * @param id 生产任务单id
	 * @return
	 */
	public R getRawMaterialRatio(Long id, Long feedId, BigDecimal num){
		Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);
		List<Map<Object, Object>> data = new ArrayList<>();
		Map<String, Object> rawMaterialRatio = new HashMap<>();
		ProductionPlanDO productionPlanDO = productionPlanService.get(id);
		HashMap<String, Object> feedMap = new HashMap<>();
		feedMap.put("planId",id);
		feedMap.put("delFlag",0);

		List<ProductionFeedingDetailDO> feedingDetailDOS = productionFeedingDetailDao.feedingItemList(feedMap);
		//获取bom信息
		Map<String, Object> map2 = new HashMap<>();
		ArrayList<Long> ids = new ArrayList<>();
		ids.add(productionPlanDO.getMaterielId());
		map2.put("bomIds", ids);
		//一级bom
		List<BomDO2> bomDOType = bomService.getDO2(map2);
		if (ObjectUtils.isEmpty(bomDOType)) {
			return R.error("操作失败");
		}
		List<Long> childIds = bomDOType.stream().map(BomDO2::getChildMaterielId).collect(Collectors.toList());
		map2.put("bomIds", childIds);
		//二级bom
		List<BomDO2> bomDOs = bomService.getDO2(map2);
		if (ObjectUtils.isEmpty(bomDOType) || bomDOType.size() <= 0) {
			return R.error("操作失败");
		}

		Map<String, BomDO2> collectChildMaterielName = bomDOType.stream()
				.collect(Collectors.toMap(BomDO2::getChildMaterielName, v -> v,(v1,v2)->v1));
		Map<Long, List<BomDO2>> bomGroup = bomDOs.stream()
				.collect(Collectors.groupingBy(BomDO2::getMaterielId));

		if (!ObjectUtils.isEmpty(productionPlanDO.getPlanCount()) && !ObjectUtils.isEmpty(num)){
			data = feedingDetailDOS.stream().map(detail -> {
				HashMap<Object, Object> map = new HashMap<>();
				map.put("materielId", detail.getMaterielId());
				map.put("materielName", ObjectUtil.isEmpty(detail.getMaterielSpecification()) ? detail.getMaterielName() : detail.getMaterielName()+"-"+detail.getMaterielSpecification());
				BigDecimal divide = ObjectUtils.isEmpty(detail.getPlanFeeding()) ? BigDecimal.ZERO : detail.getPlanFeeding().multiply(num).divide(detail.getPlanCount());
				map.put("planFeeding", divide);
				return map;
			}).collect(Collectors.toList());
		}

		List<BomDO2> childs;
		BomDO2 child;
		int j = 0;
		BomDO2 OUT = collectChildMaterielName.get("OUT");
		BomDO2 MI = collectChildMaterielName.get("MI");
		BomDO2 IN = collectChildMaterielName.get("IN");
		if(!ObjectUtils.isEmpty(IN)){

			childs = bomGroup.get(IN.getChildMaterielId());
			childs = childs.stream().collect(
					Collectors.collectingAndThen(
							Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BomDO2::getChildMaterielName))), ArrayList::new));
			if (!ObjectUtils.isEmpty(IN) && !ObjectUtils.isEmpty(childs) && childs.size() > 0) {
				for (int n = 0; n < 4; n++) {
					if (n < childs.size()) {
						child = childs.get(n);
						rawMaterialRatio.put("name" + ++j, ObjectUtils.isEmpty(child.getChildMaterielSpecification()) ? child.getChildMaterielName() : (child.getChildMaterielName() + "-" + child.getChildMaterielSpecification()));
//						rawMaterialRatio.put("name" + ++j, child.getChildMaterielName());
						rawMaterialRatio.put("id" + j, child.getChildMaterielId());
						rawMaterialRatio.put("proportion" + j, child.getStandardCount());
					} else {
						rawMaterialRatio.put("name" + ++j, "");
					}
				}
			}
		}else {
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
		}

		if(!ObjectUtils.isEmpty(MI)){

			childs = bomGroup.get(MI.getChildMaterielId());
			childs = childs.stream().collect(
					Collectors.collectingAndThen(
							Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BomDO2::getChildMaterielName))), ArrayList::new));
			if (!ObjectUtils.isEmpty(MI) && !ObjectUtils.isEmpty(childs) && childs.size() > 0) {
				for (int n = 0; n < 4; n++) {
					if (n < childs.size()) {
						child = childs.get(n);
						rawMaterialRatio.put("name" + ++j, ObjectUtils.isEmpty(child.getChildMaterielSpecification()) ? child.getChildMaterielName() : (child.getChildMaterielName() + "-" + child.getChildMaterielSpecification()));
						rawMaterialRatio.put("proportion" + j, child.getStandardCount());
						rawMaterialRatio.put("id" + j, child.getChildMaterielId());
					} else {
						rawMaterialRatio.put("name" + ++j, "");
					}
				}
			}
		}else {
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
		}

		if(!ObjectUtils.isEmpty(OUT)){

			childs = bomGroup.get(OUT.getChildMaterielId());
			childs = childs.stream().collect(
					Collectors.collectingAndThen(
							Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BomDO2::getChildMaterielName))), ArrayList::new));
			if (!ObjectUtils.isEmpty(OUT) && !ObjectUtils.isEmpty(childs) && childs.size() > 0) {
				for (int n = 0; n < 4; n++) {
					if (n < childs.size()) {
						child = childs.get(n);
						rawMaterialRatio.put("name" + ++j, ObjectUtils.isEmpty(child.getChildMaterielSpecification()) ? child.getChildMaterielName() : (child.getChildMaterielName() + "-" + child.getChildMaterielSpecification()));
						rawMaterialRatio.put("proportion" + j, child.getStandardCount());
						rawMaterialRatio.put("id" + j, child.getChildMaterielId());
					} else {
						rawMaterialRatio.put("name" + ++j, "");
					}
				}
			}
		}else {
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
		}

		results.put("rawMaterialRatio",rawMaterialRatio);
		results.put("data",data);
		return R.ok(results);
	}
	public R getRawMaterialRatio2(Long id, Long feedId, BigDecimal num, Long instructionId){
		Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);
		List<Map<Object, Object>> data = new ArrayList<>();
		Map<String, Object> rawMaterialRatio = new HashMap<>();
		ProductionPlanDO productionPlanDO = productionPlanService.get(id);
		HashMap<String, Object> feedMap = new HashMap<>();
		feedMap.put("planId",id);
		feedMap.put("delFlag",0);

		List<ProductionFeedingDetailDO> feedingDetailDOS = productionFeedingDetailDao.feedingItemList(feedMap);
		//获取bom信息
		Map<String, Object> map2 = new HashMap<>();
		ArrayList<Long> ids = new ArrayList<>();
		ids.add(productionPlanDO.getMaterielId());
		map2.put("bomIds", ids);
		//一级bom
		List<BomDO2> bomDOType = bomService.getDO2(map2);
		if (ObjectUtils.isEmpty(bomDOType)) {
			return R.error("操作失败");
		}
		List<Long> childIds = bomDOType.stream().map(BomDO2::getChildMaterielId).collect(Collectors.toList());
		map2.put("bomIds", childIds);
		//二级bom
		List<BomDO2> bomDOs = bomService.getDO2(map2);
		if (ObjectUtils.isEmpty(bomDOType) || bomDOType.size() <= 0) {
			return R.error("操作失败");
		}

		Map<String, BomDO2> collectChildMaterielName = bomDOType.stream()
				.collect(Collectors.toMap(BomDO2::getChildMaterielName, v -> v,(v1,v2)->v1));
		Map<Long, List<BomDO2>> bomGroup = bomDOs.stream()
				.collect(Collectors.groupingBy(BomDO2::getMaterielId));

		if (!ObjectUtils.isEmpty(productionPlanDO.getPlanCount()) && !ObjectUtils.isEmpty(num)){
			data = feedingDetailDOS.stream().map(detail -> {
				HashMap<Object, Object> map = new HashMap<>();
				map.put("materielId", detail.getMaterielId());
				map.put("materielName", ObjectUtil.isEmpty(detail.getMaterielSpecification()) ? detail.getMaterielName() : detail.getMaterielName()+"-"+detail.getMaterielSpecification());
				BigDecimal divide = ObjectUtils.isEmpty(detail.getPlanFeeding()) ? BigDecimal.ZERO : detail.getPlanFeeding().multiply(num).divide(detail.getPlanCount());
				map.put("planFeeding", divide);
				return map;
			}).collect(Collectors.toList());
		}

		if (ObjectUtil.isNotEmpty(instructionId)){

			Map<String, Object> instructionDO = moldingProductionInstructionDao.getDetailInfo(instructionId);
			JSONObject jsonObject = ObjectUtils.isEmpty(instructionDO.get("rawMaterialRatio")) ? new JSONObject() : JSON.parseObject(instructionDO.get("rawMaterialRatio").toString());
			results.put("rawMaterialRatio",jsonObject);
			results.put("data",data);
			return R.ok(results);
		}


		List<BomDO2> childs;
		BomDO2 child;
		int j = 0;
		BomDO2 OUT = collectChildMaterielName.get("OUT");
		BomDO2 MI = collectChildMaterielName.get("MI");
		BomDO2 IN = collectChildMaterielName.get("IN");
		if(!ObjectUtils.isEmpty(IN)){

			childs = bomGroup.get(IN.getChildMaterielId());
			childs = childs.stream().collect(
					Collectors.collectingAndThen(
							Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BomDO2::getChildMaterielName))), ArrayList::new));
			if (!ObjectUtils.isEmpty(IN) && !ObjectUtils.isEmpty(childs) && childs.size() > 0) {
				for (int n = 0; n < 4; n++) {
					if (n < childs.size()) {
						child = childs.get(n);
						rawMaterialRatio.put("name" + ++j, ObjectUtils.isEmpty(child.getChildMaterielSpecification()) ? child.getChildMaterielName() : (child.getChildMaterielName() + "-" + child.getChildMaterielSpecification()));
//						rawMaterialRatio.put("name" + ++j, child.getChildMaterielName());
						rawMaterialRatio.put("id" + j, child.getChildMaterielId());
						rawMaterialRatio.put("proportion" + j, child.getStandardCount());
					} else {
						rawMaterialRatio.put("name" + ++j, "");
					}
				}
			}
		}else {
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
		}

		if(!ObjectUtils.isEmpty(MI)){

			childs = bomGroup.get(MI.getChildMaterielId());
			childs = childs.stream().collect(
					Collectors.collectingAndThen(
							Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BomDO2::getChildMaterielName))), ArrayList::new));
			if (!ObjectUtils.isEmpty(MI) && !ObjectUtils.isEmpty(childs) && childs.size() > 0) {
				for (int n = 0; n < 4; n++) {
					if (n < childs.size()) {
						child = childs.get(n);
						rawMaterialRatio.put("name" + ++j, ObjectUtils.isEmpty(child.getChildMaterielSpecification()) ? child.getChildMaterielName() : (child.getChildMaterielName() + "-" + child.getChildMaterielSpecification()));
						rawMaterialRatio.put("proportion" + j, child.getStandardCount());
						rawMaterialRatio.put("id" + j, child.getChildMaterielId());
					} else {
						rawMaterialRatio.put("name" + ++j, "");
					}
				}
			}
		}else {
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
		}

		if(!ObjectUtils.isEmpty(OUT)){

			childs = bomGroup.get(OUT.getChildMaterielId());
			childs = childs.stream().collect(
					Collectors.collectingAndThen(
							Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BomDO2::getChildMaterielName))), ArrayList::new));
			if (!ObjectUtils.isEmpty(OUT) && !ObjectUtils.isEmpty(childs) && childs.size() > 0) {
				for (int n = 0; n < 4; n++) {
					if (n < childs.size()) {
						child = childs.get(n);
						rawMaterialRatio.put("name" + ++j, ObjectUtils.isEmpty(child.getChildMaterielSpecification()) ? child.getChildMaterielName() : (child.getChildMaterielName() + "-" + child.getChildMaterielSpecification()));
						rawMaterialRatio.put("proportion" + j, child.getStandardCount());
						rawMaterialRatio.put("id" + j, child.getChildMaterielId());
					} else {
						rawMaterialRatio.put("name" + ++j, "");
					}
				}
			}
		}else {
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
		}

		results.put("rawMaterialRatio",rawMaterialRatio);
		results.put("data",data);
		return R.ok(results);
	}

	/**
	 * 获得产品的子bom信息
	 * @param id 生产任务单id
	 * @return
	 */
	public Map<String, Object> getRawMaterialRatio2(Long id, Long feedId, BigDecimal num){
		Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);
//		List<Map<Object, Object>> data = new ArrayList<>();
		Map<String, Object> rawMaterialRatio = new HashMap<>();
		ProductionPlanDO productionPlanDO = productionPlanService.get(id);
		HashMap<String, Object> feedMap = new HashMap<>();
		feedMap.put("planId",id);
		feedMap.put("delFlag",0);

//		List<ProductionFeedingDetailDO> feedingDetailDOS = productionFeedingDetailDao.feedingItemList(feedMap);
		//获取bom信息
		Map<String, Object> map2 = new HashMap<>();
		ArrayList<Long> ids = new ArrayList<>();
		ids.add(productionPlanDO.getMaterielId());
		map2.put("bomIds", ids);
		//一级bom
		List<BomDO2> bomDOType = bomService.getDO2(map2);
		if (ObjectUtils.isEmpty(bomDOType)) {
			return R.error("操作失败");
		}
		List<Long> childIds = bomDOType.stream().map(BomDO2::getChildMaterielId).collect(Collectors.toList());
		map2.put("bomIds", childIds);
		//二级bom
		List<BomDO2> bomDOs = bomService.getDO2(map2);
		if (ObjectUtils.isEmpty(bomDOType) || bomDOType.size() <= 0) {
			return R.error("操作失败");
		}

		Map<String, BomDO2> collectChildMaterielName = bomDOType.stream()
				.collect(Collectors.toMap(BomDO2::getChildMaterielName, v -> v,(v1,v2)->v1));
		Map<Long, List<BomDO2>> bomGroup = bomDOs.stream()
				.collect(Collectors.groupingBy(BomDO2::getMaterielId));

//		if (!ObjectUtils.isEmpty(productionPlanDO.getPlanCount()) && !ObjectUtils.isEmpty(num)){
//			data = feedingDetailDOS.stream().map(detail -> {
//				HashMap<Object, Object> map = new HashMap<>();
//				map.put("materielId", detail.getMaterielId());
//				map.put("materielName", ObjectUtil.isEmpty(detail.getMaterielSpecification()) ? detail.getMaterielName() : detail.getMaterielName()+"-"+detail.getMaterielSpecification());
//				BigDecimal divide = ObjectUtils.isEmpty(detail.getPlanFeeding()) ? BigDecimal.ZERO : detail.getPlanFeeding().multiply(num).divide(detail.getPlanCount());
//				map.put("planFeeding", divide);
//				return map;
//			}).collect(Collectors.toList());
//		}

		List<BomDO2> childs;
		BomDO2 child;
		int j = 0;
		BomDO2 OUT = collectChildMaterielName.get("OUT");
		BomDO2 MI = collectChildMaterielName.get("MI");
		BomDO2 IN = collectChildMaterielName.get("IN");
		if(!ObjectUtils.isEmpty(IN)){

			childs = bomGroup.get(IN.getChildMaterielId());
			childs = childs.stream().collect(
					Collectors.collectingAndThen(
							Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BomDO2::getChildMaterielName))), ArrayList::new));
			if (!ObjectUtils.isEmpty(IN) && !ObjectUtils.isEmpty(childs) && childs.size() > 0) {
				for (int n = 0; n < 4; n++) {
					if (n < childs.size()) {
						child = childs.get(n);
						rawMaterialRatio.put("name" + ++j, ObjectUtils.isEmpty(child.getChildMaterielSpecification()) ? child.getChildMaterielName() : (child.getChildMaterielName() + "-" + child.getChildMaterielSpecification()));
//						rawMaterialRatio.put("name" + ++j, child.getChildMaterielName());
						rawMaterialRatio.put("id" + j, child.getChildMaterielId());
						rawMaterialRatio.put("proportion" + j, child.getStandardCount());
					} else {
						rawMaterialRatio.put("name" + ++j, "");
					}
				}
			}
		}else {
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
		}

		if(!ObjectUtils.isEmpty(MI)){

			childs = bomGroup.get(MI.getChildMaterielId());
			childs = childs.stream().collect(
					Collectors.collectingAndThen(
							Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BomDO2::getChildMaterielName))), ArrayList::new));
			if (!ObjectUtils.isEmpty(MI) && !ObjectUtils.isEmpty(childs) && childs.size() > 0) {
				for (int n = 0; n < 4; n++) {
					if (n < childs.size()) {
						child = childs.get(n);
						rawMaterialRatio.put("name" + ++j, ObjectUtils.isEmpty(child.getChildMaterielSpecification()) ? child.getChildMaterielName() : (child.getChildMaterielName() + "-" + child.getChildMaterielSpecification()));
						rawMaterialRatio.put("proportion" + j, child.getStandardCount());
						rawMaterialRatio.put("id" + j, child.getChildMaterielId());
					} else {
						rawMaterialRatio.put("name" + ++j, "");
					}
				}
			}
		}else {
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
		}

		if(!ObjectUtils.isEmpty(OUT)){

			childs = bomGroup.get(OUT.getChildMaterielId());
			childs = childs.stream().collect(
					Collectors.collectingAndThen(
							Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(BomDO2::getChildMaterielName))), ArrayList::new));
			if (!ObjectUtils.isEmpty(OUT) && !ObjectUtils.isEmpty(childs) && childs.size() > 0) {
				for (int n = 0; n < 4; n++) {
					if (n < childs.size()) {
						child = childs.get(n);
						rawMaterialRatio.put("name" + ++j, ObjectUtils.isEmpty(child.getChildMaterielSpecification()) ? child.getChildMaterielName() : (child.getChildMaterielName() + "-" + child.getChildMaterielSpecification()));
						rawMaterialRatio.put("proportion" + j, child.getStandardCount());
						rawMaterialRatio.put("id" + j, child.getChildMaterielId());
					} else {
						rawMaterialRatio.put("name" + ++j, "");
					}
				}
			}
		}else {
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
			rawMaterialRatio.put("name" + ++j, "");
		}

		results.put("rawMaterialRatio",rawMaterialRatio);
//		results.put("data",data);
		return results;
	}


}

